#include "stateManager.h"
#include "state.h"
#include "rcore.h"
#include "InputManager.h"

template<> StateManager* gcore::Singleton<StateManager>::ms_Singleton = 0;

StateManager::StateManager()
{
	mInputManager = 0;
}

StateManager::~StateManager()
{
	// clean up all the states
	while (!mStates.empty()) {
		mStates.back()->exit();
		mStates.pop_back();
	}
	if (mInputManager)
		delete mInputManager;
	if (renderCore)
	{
		renderCore->Shutdown();
		delete renderCore;
	}
}

void StateManager::start(State* state)
{
    //**********setup the renderer here***********//
	renderCore = new RenderCore();
	renderCore->init();

	//*********Initialize other managers***********//
	//ObjectManager mObjectManager = new ObjectManager();
	//mObjectManager->init();

	//sound? Network?

    //***************load resources****************//

	//*****Change state and start rendering********//
	changeState(state);

	// The input manager is initialized in the
	// RenderCore's start function. This is because
	// we need the HWND handle to be created before
	// initialization of the InputManager.
	renderCore->Start();
}

State* StateManager::GetState()
{
	return mStates.back();
}

void StateManager::changeState(State* state)
{
	// cleanup the current state
	if ( !mStates.empty() ) {
		mStates.back()->exit();
		mStates.pop_back();
	}

	// store and init the new state
	mStates.push_back(state);
	mStates.back()->enter();
}

void StateManager::pushState(State* state)
{
	// pause current state
	if ( !mStates.empty() ) {
		mStates.back()->pause();
	}

	// store and init the new state
	mStates.push_back(state);
	mStates.back()->enter();
}

void StateManager::popState()
{
	// cleanup the current state
	if ( !mStates.empty() ) {
		mStates.back()->exit();
		mStates.pop_back();
	}

	// resume previous state
	if ( !mStates.empty() ) {
		mStates.back()->resume();
	}
}

bool StateManager::keyPressed( const OIS::KeyEvent& e)
{
	// call keyPressed of current state
	mStates.back()->keyPressed(e);

	return true;
}

bool StateManager::keyReleased( const OIS::KeyEvent& e)
{
	// call keyReleased of current state
	mStates.back()->keyReleased(e);

	return true;
}

bool StateManager::mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id )
{
	mStates.back()->mousePressed(e, id);

	return true;
}

bool StateManager::mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id )
{
	mStates.back()->mouseReleased(e, id);
	return true;
}

bool StateManager::mouseMoved( const OIS::MouseEvent &e )
{
	mStates.back()->mouseMoved(e);
	return true;
}

bool StateManager::buttonPressed( const OIS::JoyStickEvent &e, int val)
{
	mStates.back()->buttonPressed(e, val);
	return true;
}

bool StateManager::buttonReleased( const OIS::JoyStickEvent &e, int val)
{
	mStates.back()->buttonReleased(e, val);
	return true;
}

bool StateManager::axisMoved( const OIS::JoyStickEvent &e, int val)
{
	mStates.back()->axisMoved(e, val);
	return true;
}

StateManager* StateManager::getSingletonPtr(void)
{
	return ms_Singleton;
}

StateManager& StateManager::getSingleton(void)
{
	assert(ms_Singleton);
	return *ms_Singleton;
}
